package com.runfast.waimai.service.impl;

import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayMobilePublicMultiMediaClient;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.response.AlipayTradeAppPayResponse;
import com.alipay.api.response.AlipayTradeFastpayRefundQueryResponse;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.alipay.api.response.AlipayTradeRefundResponse;
import com.runfast.common.dao.model.RunfastCuser;
import com.runfast.common.security.spring.UserDataDetails;
import com.runfast.common.service.RunfastCuserService;
import com.runfast.common.web.entity.Result;
import com.runfast.common.web.entity.ResultCode;
import com.runfast.pay.Channel;
import com.runfast.pay.alipay.AlipayConfig;
import com.runfast.pay.service.AlipayService;
import com.runfast.pay.service.PayService;
import com.runfast.pay.service.WxpayService;
import com.runfast.pay.wxpay.WXPay;
import com.runfast.pay.wxpay.WXPayConstants;
import com.runfast.pay.wxpay.WXPayUtil;
import com.runfast.waimai.dao.model.*;
import com.runfast.waimai.service.*;
import com.runfast.waimai.task.async.MessagePushTask;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.crypto.cipher.CryptoCipher;
import org.apache.commons.crypto.cipher.CryptoCipherFactory;
import org.apache.commons.crypto.utils.Utils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.crypto.spec.SecretKeySpec;
import java.io.IOException;
import java.math.BigDecimal;
import java.text.ParseException;
import java.util.*;

import static com.runfast.waimai.dao.model.RunfastActivity.CreateType.business;
import static com.runfast.waimai.dao.model.RunfastGoodsSellRecord.Status.*;

import static javax.crypto.Cipher.DECRYPT_MODE;


/**
 * @author: lijin
 * @date: 2018年03月30日
 */

@Service("wmPayService")
@Slf4j
public class PayServiceImpl implements PayService {
    @Resource
    private WXPay wxAppPay;

    @Resource
    private WXPay wxPublicPay;

    @Resource
    private WXPay wxMiniPay;

    @Autowired
    private AlipayService alipayService;

    @Autowired
    private WxpayService wxpayService;

    @Autowired
    private RunfastGoodsSellRecordService orderService;

    @Autowired
    private RunfastRefundService refundService;

    @Autowired
    private RunfastGoodsSellOutStatusService statusService;

    @Autowired
    private MessagePushTask messagePushTask;

    @Autowired
    private RunfastCuserService cuserService;

    @Autowired
    private RunfastBusinessService businessService;

    @Autowired
    private RunfastAccountrecordService accountrecordService;


    private String alipayPayNotifyUrl = "http://www.gxptkc.com";

    private String wxpayPayNotifyUrl = "http://www.gxptkc.com";

    private String wxpayRefundNotifyUrl = "http://www.gxptkc.com";

    @Override
    public Result prepay(Channel channel, String orderNo, String clientIp) {
        Validate.notNull(channel, "channel 不能为null");
        Validate.notBlank(orderNo, "orderNo 不能为空");
        Validate.notBlank(clientIp, "clientIp 不能为空");

        RunfastGoodsSellRecordExample orderExample = new RunfastGoodsSellRecordExample();
        orderExample.createCriteria()
                .andOrderCodeEqualTo(orderNo);

        List<RunfastGoodsSellRecord> orders = orderService.selectByExample(orderExample);
        if (orders.isEmpty()) return Result.fail(ResultCode.ORDER_NOT_EXIST);
        RunfastGoodsSellRecord order = orders.get(0);

        Integer cuserId = order.getUserId();
        UserDataDetails<RunfastCuser> principal = (UserDataDetails<RunfastCuser>)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        RunfastCuser cuser = principal.getData();
        if(cuser.getId()!=cuserId.intValue()) return Result.fail(ResultCode.FAIL, "待支付的订单不属于当前用户");
        String openId = cuser.getMiniOpenId();


        Integer status = order.getStatus();
        if (status == RunfastGoodsSellRecord.Status.canceled.getCode()) return Result.fail(ResultCode.FAIL, "订单已经取消");
        if (status != RunfastGoodsSellRecord.Status.created.getCode()) return Result.fail(ResultCode.PAY_STATUS_UNPAID, "只能对新下的订单进行支付");

        int amountPayable = order.getTotalpay().multiply(BigDecimal.valueOf(100)).intValue();
        String goodsDescription = "外卖订单商品描述";

        RunfastGoodsSellRecord orderUpdate = new RunfastGoodsSellRecord();
        orderUpdate.setId(order.getId());
        orderUpdate.setPayType(channel.getCode());
        orderService.updateByPrimaryKeySelective(orderUpdate);
        switch (channel) {
            case ALIPAY_APP:
                Map<String, String> params = alipayService.prepay(orderNo, amountPayable, goodsDescription, "QUICK_MSECURITY_PAY", "3h", alipayPayNotifyUrl);

                String prepay = "";
                try {
                    prepay = AlipayMobilePublicMultiMediaClient.buildQuery(params, AlipayConfig.input_charset);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                /*StringBuilder postParam = new StringBuilder();
                for (Map.Entry<String, String> entry : prepay.entrySet()) {
                    String key = entry.getKey();
                    String value = entry.getValue();

                    postParam.append("&");
                    try {
                        postParam.append(key +"=" + URLEncoder.encode(value, AlipayConfig.input_charset));
                    } catch (UnsupportedEncodingException e) {
                        e.printStackTrace();
                    }


                }*/
                return Result.ok("预下单成功", prepay);
            case WXPAY_APP: {

                Map<String, String> stringMap = wxpayService.prepay(channel, orderNo, "跑腿快车外卖款", amountPayable, clientIp, wxpayPayNotifyUrl,openId);

                String returnCode = stringMap.get("return_code");
                if ("SUCCESS".equals(returnCode)) {
                    String resultCode = stringMap.get("result_code");
                    if (!"SUCCESS".equals(resultCode))
                        return Result.fail(ResultCode.PAY_PREPAY_FAIL, stringMap.get("err_code_des"));


                    HashMap<String, String> reqData = new HashMap<>();
                    reqData.put("appid", wxAppPay.getConfig().getAppID());
                    reqData.put("partnerid", wxAppPay.getConfig().getMchID());
                    reqData.put("noncestr", WXPayUtil.generateUUID());
                    reqData.put("timestamp", (int) (new Date().getTime() / 1000) + "");
                    reqData.put("prepayid", stringMap.get("prepay_id"));
                    reqData.put("package", "Sign=WXPay");

                    try {
                        String signature = WXPayUtil.generateSignature(reqData, wxAppPay.getConfig().getKey(), WXPayConstants.SignType.HMACSHA256);
                        reqData.put("sign", signature);
                    } catch (Exception e) {
                        return Result.fail(ResultCode.FAIL, "生成签名失败");
                    }

                    return Result.ok("预下单成功", reqData);
                } else {
                    return Result.fail(ResultCode.PAY_PREPAY_FAIL, stringMap.get("return_msg"));
                }
            }
            case WXPAY_PUBLIC:
            case WXPAY_MINI: {
                if(StringUtils.isBlank(openId)) return Result.fail(ResultCode.FAIL, "该用户未绑定openid");
                Map<String, String> stringMap = wxpayService.prepay(channel, orderNo, "跑腿快车外卖款", amountPayable, clientIp, wxpayPayNotifyUrl,openId);

                String returnCode = stringMap.get("return_code");
                if ("SUCCESS".equals(returnCode)) {
                    String resultCode = stringMap.get("result_code");
                    if (!"SUCCESS".equals(resultCode))
                        return Result.fail(ResultCode.PAY_PREPAY_FAIL, stringMap.get("err_code_des"));


                    HashMap<String, String> reqData = new HashMap<>();
                    reqData.put("appId", wxMiniPay.getConfig().getAppID());
                    reqData.put("nonceStr", WXPayUtil.generateUUID());
                    reqData.put("timeStamp", (int) (new Date().getTime() / 1000) + "");
                    reqData.put("signType", wxMiniPay.getSignType()==WXPayConstants.SignType.MD5?WXPayConstants.MD5:WXPayConstants.HMACSHA256);
                    reqData.put("package", "prepay_id="+stringMap.get("prepay_id"));

                    try {
                        String signature = WXPayUtil.generateSignature(reqData, wxMiniPay.getConfig().getKey(), WXPayConstants.SignType.HMACSHA256);
                        reqData.put("paySign", signature);
                    } catch (Exception e) {
                        log.error("", e);
                        return Result.fail(ResultCode.FAIL, "生成签名失败");
                    }

                    return Result.ok("预下单成功", reqData);
                } else {
                    return Result.fail(ResultCode.PAY_PREPAY_FAIL, stringMap.get("return_msg"));
                }
            }
            default:
                return Result.fail(ResultCode.PAY_CHANNEL_NOT_SUPPORT);
        }

    }

    public Result refund(RunfastRefund refund) {

        Integer orderId = refund.getOrder_id();
        String orderNo = refund.getOrder_no();
        String refundNo = refund.getRefund_no();


        RunfastGoodsSellRecord order = orderService.selectByPrimaryKey(orderId);
        if (order==null) return Result.fail(ResultCode.ORDER_NOT_EXIST);
        Integer isPay = order.getIsPay();
        if (isPay !=1) return Result.fail(ResultCode.PAY_STATUS_UNPAID, "订单未支付，不能发起退款");
        BigDecimal totalpay = order.getTotalpay();
        Integer amountPaid = totalpay.multiply(BigDecimal.valueOf(100)).intValue();
        Integer refundAmount = refund.getAmount();


        Integer payType = order.getPayType();
        if(payType==null)return Result.fail(ResultCode.FAIL, "订单还未支付");
        Channel channel = null;
        Channel[] values = Channel.values();
        for (Channel value : values) {
            if(value.getCode()==payType) {
                channel = value;
                break;
            }
        }
        switch (channel) {
            case ALIPAY_APP:

                AlipayTradeRefundResponse refundResponse = alipayService.applyRefund(orderNo, refundNo, refundAmount);

                if (!refundResponse.isSuccess()) {
                    RunfastRefund refundUpdated = new RunfastRefund();
                    refundUpdated.setId(refund.getId());
                    refundUpdated.setStatus(RunfastRefund.Status.fail.getCode());
                    refundUpdated.setFailure_code(refundResponse.getSubCode());
                    refundUpdated.setFailure_msg(refundResponse.getSubMsg());
                    refundService.updateByPrimaryKeySelective(refundUpdated);
                    refundUpdated.setUpdate_time(new Date());
                    return Result.fail(ResultCode.PAY_REFUND_FAIL, refundResponse.getSubMsg());
                } else {
                    RunfastRefund refundUpdated = new RunfastRefund();
                    refundUpdated.setId(refund.getId());
                    refundUpdated.setStatus(RunfastRefund.Status.success.getCode());
                    refundUpdated.setSucceed(true);
                    refundUpdated.setTime_succeed(new Date());
                    refundUpdated.setTransaction_no(refundResponse.getTradeNo());
                    refundUpdated.setUpdate_time(new Date());
                    refundService.updateByPrimaryKeySelective(refundUpdated);

                    return Result.ok("退款申请成功");
                }
            case WXPAY_APP:
            case WXPAY_PUBLIC:
            case WXPAY_MINI:
                Map<String, String> stringMap = wxpayService.applyRefund(channel, orderNo, refundNo, amountPaid, refundAmount, wxpayRefundNotifyUrl);

                String returnCode = stringMap.get("return_code");
                if ("SUCCESS".equals(returnCode)) {
                    String resultCode = stringMap.get("result_code");
                    if (!"SUCCESS".equals(resultCode)) {
                        RunfastRefund refundUpdated = new RunfastRefund();
                        refundUpdated.setId(refund.getId());
                        refundUpdated.setStatus(RunfastRefund.Status.fail.getCode());
                        refundUpdated.setFailure_code(stringMap.get("err_code"));
                        refundUpdated.setFailure_msg(stringMap.get("err_code_des"));
                        refundUpdated.setUpdate_time(new Date());
                        refundService.updateByPrimaryKeySelective(refundUpdated);

                        return Result.fail(ResultCode.PAY_REFUND_FAIL, stringMap.get("err_code_des"));
                    } else {

                        RunfastRefund refundUpdated = new RunfastRefund();
                        refundUpdated.setId(refund.getId());
                        refundUpdated.setStatus(RunfastRefund.Status.success.getCode());
                        refundUpdated.setSucceed(true);
                        refundUpdated.setTime_succeed(new Date());
                        refundUpdated.setTransaction_no(stringMap.get("transaction_id"));
                        refundUpdated.setUpdate_time(new Date());
                        refundService.updateByPrimaryKeySelective(refundUpdated);

                        return Result.ok("退款申请成功（退款有一定延时，用零钱支付的退款20分钟内到账，银行卡支付的退款3个工作日后）");
                    }
                } else {
                    RunfastRefund refundUpdated = new RunfastRefund();
                    refundUpdated.setId(refund.getId());
                    refundUpdated.setStatus(RunfastRefund.Status.fail.getCode());
                    refundUpdated.setFailure_code(stringMap.get(returnCode));
                    refundUpdated.setFailure_msg(stringMap.get("return_msg"));
                    refundUpdated.setUpdate_time(new Date());
                    refundService.updateByPrimaryKeySelective(refundUpdated);
                    return Result.fail(ResultCode.PAY_REFUND_FAIL, stringMap.get("return_msg"));
                }
            case BALANCE: //退还至钱包
                Integer userId = order.getUserId();
                RunfastCuser cuser = cuserService.selectByPrimaryKey(userId);

                BigDecimal remainder = cuser.getRemainder();
                remainder = remainder==null?BigDecimal.valueOf(0):remainder;

                BigDecimal totalremainder = cuser.getTotalremainder();
                if(totalremainder==null||totalremainder.compareTo(remainder)==-1) totalremainder = remainder;


                /**
                    * 更新用户余额
                    */
                RunfastCuser cuserUpdate = new RunfastCuser();
                cuserUpdate.setId(cuser.getId());
                cuserUpdate.setRemainder(remainder.add(totalpay));


                cuserUpdate.setTotalremainder(totalremainder.add(totalpay));

                cuserService.updateByPrimaryKeySelective(cuserUpdate);

                /**
                 * 账户变动清单
                 */
                RunfastAccountrecord accountRecord = new RunfastAccountrecord();

                accountRecord.setType(3);//退款
                accountRecord.setTypename("退款");
                accountRecord.setShowtype(0);
                accountRecord.setMonetary(totalpay);//退回金额
                accountRecord.setBeforemonety(remainder);
                accountRecord.setBalance(remainder.add(totalpay));
                accountRecord.setCardnumber(order.getOrderCode());
                accountRecord.setCid(cuser.getId());
                accountRecord.setName(cuser.getName());
                accountRecord.setMobile(cuser.getMobile());
                accountRecord.setCreateTime(new Date());
                accountRecord.setGenreType(1);//用户

                accountrecordService.insertSelective(accountRecord);


                RunfastRefund refundUpdated = new RunfastRefund();
                refundUpdated.setId(refund.getId());
                refundUpdated.setStatus(RunfastRefund.Status.success.getCode());
                refundUpdated.setSucceed(true);
                refundUpdated.setTime_succeed(new Date());
                refundUpdated.setUpdate_time(new Date());
                refundService.updateByPrimaryKeySelective(refundUpdated);
                return Result.ok("退款成功");
            default:
                return Result.fail(ResultCode.PAY_CHANNEL_NOT_SUPPORT);
        }
    }
    public Result refund(String orderNo, String refundNo, Integer refundAmount, String description) {
        Validate.notBlank(orderNo, "orderNo 不能为空");
        Validate.notBlank(refundNo, "refundNo 不能为空");
        Validate.notNull(refundAmount, "refundAmount 不能为空");

        RunfastGoodsSellRecordExample orderExample = new RunfastGoodsSellRecordExample();
        orderExample.createCriteria()
                .andOrderCodeEqualTo(orderNo);

        List<RunfastGoodsSellRecord> orders = orderService.selectByExample(orderExample);
        if (orders.isEmpty()) return Result.fail(ResultCode.ORDER_NOT_EXIST);
        RunfastGoodsSellRecord order = orders.get(0);
        Integer isPay = order.getIsPay();
        if (isPay!=null&&isPay !=1) return Result.fail(ResultCode.PAY_STATUS_UNPAID, "订单未支付，不能发起退款");
        Integer amountPaid = order.getTotalpay().intValue();

        if (refundAmount<=amountPaid ) throw new RuntimeException("refundAmount必须小于等于payAmount");

        RunfastRefund refund = new RunfastRefund();
        refund.setStatus(RunfastRefund.Status.pending.getCode());
        refund.setAmount(refundAmount);
        refund.setRefund_no(refundNo);
        refund.setOrder_no(orderNo);
        refund.setOrder_id(order.getId());
        refund.setCreate_time(new Date());
        refund.setDescription(description);
        refund.setUpdate_time(new Date());

        refundService.insertSelective(refund);

        return refund(refund);
    }
    @Override
    public Result orderQuery(String orderNo) {
        Validate.notBlank(orderNo, "orderNo 不能为空");

        RunfastGoodsSellRecordExample orderExample = new RunfastGoodsSellRecordExample();
        orderExample.createCriteria()
                .andOrderCodeEqualTo(orderNo);

        List<RunfastGoodsSellRecord> orders = orderService.selectByExample(orderExample);
        if (orders.isEmpty()) return Result.fail(ResultCode.ORDER_NOT_EXIST);
        RunfastGoodsSellRecord order = orders.get(0);

        Integer payType = order.getPayType();
        if(payType==null)return Result.fail(ResultCode.FAIL, "订单还未支付");
        Channel channel = null;
        Channel[] values = Channel.values();
        for (Channel value : values) {
            if(value.getCode()==payType) {
                channel = value;
                break;
            }
        }


        switch (channel) {
            case ALIPAY_APP:
                AlipayTradeQueryResponse queryResponse = alipayService.orderQuery(orderNo);

                if (!queryResponse.isSuccess())
                    return Result.fail(ResultCode.PAY_ORDER_QUERY_FAIL, queryResponse.getSubMsg());
                else {
                    String tradeStatus = queryResponse.getTradeStatus();
/*                    交易状态：WAIT_BUYER_PAY（交易创建，等待买家付款）、TRADE_CLOSED（未付款交易超时关闭，或支付完成后全额退款）、TRADE_SUCCESS（交易支付成功）、TRADE_FINISHED（交易结束，不可退款）*/

                    String statusMsg = "";
                    switch (tradeStatus) {
                        case "TRADE_SUCCESS":
                            statusMsg = "支付成功";
                            onPaidSuccess(order);
                            return Result.ok(statusMsg);
                        case "WAIT_BUYER_PAY":
                            statusMsg = "交易创建，等待买家付款";
                            break;
                        case "TRADE_CLOSED":
                            statusMsg = "未付款交易超时关闭，或支付完成后全额退款";
                            break;

                        case "TRADE_FINISHED":
                            statusMsg = "交易结束，不可退款";
                            break;
                        default:
                            statusMsg = "未知的支付状态";
                    }
                    return Result.fail(ResultCode.FAIL, statusMsg);
                }
            case WXPAY_APP:
            case WXPAY_PUBLIC:
            case WXPAY_MINI:
                Map<String, String> stringMap = wxpayService.orderQuery(channel, orderNo);

                String returnCode = stringMap.get("return_code");
                if ("SUCCESS".equals(returnCode)) {
                    String resultCode = stringMap.get("result_code");
                    if (!"SUCCESS".equals(resultCode))
                        return Result.fail(ResultCode.PAY_ORDER_QUERY_FAIL, stringMap.get("err_code_des"));
                    else {
                        /*SUCCESS—支付成功

                        REFUND—转入退款

                        NOTPAY—未支付

                        CLOSED—已关闭

                        REVOKED—已撤销（刷卡支付）

                        USERPAYING--用户支付中

                        PAYERROR--支付失败(其他原因，如银行返回失败)

                        支付状态机请见下单API页面*/
                        String tradeState = stringMap.get("trade_state");
                        String statusMsg = "";
                        switch (tradeState) {
                            case "SUCCESS":
                                statusMsg = "支付成功";
                                onPaidSuccess(order);
                                return Result.ok(statusMsg);
                            case "REFUND":
                                statusMsg = "转入退款";
                                break;
                            case "NOTPAY":
                                statusMsg = "未支付";
                                break;
                            case "CLOSED":
                                statusMsg = "已关闭";
                                break;
                            case "REVOKED":
                                statusMsg = "已撤销（刷卡支付）";
                                break;
                            case "USERPAYING":
                                statusMsg = "用户支付中";
                                break;
                            case "PAYERROR":
                                statusMsg = "支付失败(其他原因，如银行返回失败)";
                                break;
                            default:
                                statusMsg = "未知的支付状态";
                        }
                        return Result.fail(ResultCode.FAIL,statusMsg);
                    }
                } else {
                    return Result.fail(ResultCode.PAY_ORDER_QUERY_FAIL, stringMap.get("return_msg"));
                }
            case BALANCE:
                Integer isPay = order.getIsPay();
                if(isPay!=null&&isPay==1) return Result.ok("已支付");
                else return Result.fail(ResultCode.FAIL,"未支付");
            default:
                return Result.fail(ResultCode.PAY_CHANNEL_NOT_SUPPORT);
        }


    }


    @Override
    public Result refundQuery(String refundNo) {

        RunfastRefundExample refundExample = new RunfastRefundExample();
        refundExample.createCriteria().andRefund_noEqualTo(refundNo);
        List<RunfastRefund> refunds = refundService.selectByExample(refundExample);
        if (refunds.isEmpty()) return Result.fail(ResultCode.PARAMETER_ERROR, "不存在refundNo 对应的退款记录");

        RunfastRefund refund = refunds.get(0);
        Integer orderId = refund.getOrder_id();
        RunfastGoodsSellRecord order = orderService.selectByPrimaryKey(orderId);
        Integer payType = order.getPayType();
        if(payType==null)return Result.fail(ResultCode.FAIL, "订单还未支付");
        Channel channel = null;
        Channel[] values = Channel.values();
        for (Channel value : values) {
            if(value.getCode()==payType) {
                channel = value;
                break;
            }
        }

        switch (channel) {
            case ALIPAY_APP:
                AlipayTradeFastpayRefundQueryResponse response = alipayService.refundQuery(refundNo);

                if (!response.isSuccess())
                    return Result.fail(ResultCode.PAY_REFUND_FAIL, response.getSubMsg());
                else {
                    String status = response.getRefundStatus();
                    /*REFUND_PROCESSING 退款处理中；REFUND_SUCCESS 退款处理成功；REFUND_FAIL 退款失败;*/

                    String statusMsg = "";
                    switch (status) {
                        case "REFUND_PROCESSING":
                            statusMsg = "退款处理中";
                            break;
                        case "REFUND_SUCCESS":
                            statusMsg = "退款处理成功";

                            break;
                        case "REFUND_FAIL":
                            statusMsg = "退款失败";
                            break;
                        default:
                            statusMsg = "未知的退款状态";
                    }
                    return Result.ok(statusMsg, status);
                }
            case WXPAY_APP:
            case WXPAY_PUBLIC:
            case WXPAY_MINI:
                Map<String, String> stringMap = wxpayService.refundrQuery(channel, refundNo);

                String returnCode = stringMap.get("return_code");
                if ("SUCCESS".equals(returnCode)) {
                    String resultCode = stringMap.get("result_code");
                    if (!"SUCCESS".equals(resultCode))
                        return Result.fail(ResultCode.PAY_REFUND_FAIL, stringMap.get("err_code_des"));
                    else {
                        /*退款状态：

                        SUCCESS—退款成功

                        REFUNDCLOSE—退款关闭。

                        PROCESSING—退款处理中

                        CHANGE—退款异常，退款到银行发现用户的卡作废或者冻结了，导致原路退款银行卡失败，可前往商户平台（pay.weixin.qq.com）-交易中心，手动处理此笔退款。$n为下标，从0开始编号。
*/
                        String status = stringMap.get("refund_status");
                        String statusMsg = "";
                        switch (status) {
                            case "SUCCESS":
                                statusMsg = "退款成功";
                                break;
                            case "REFUNDCLOSE":
                                statusMsg = "退款关闭";
                                break;
                            case "PROCESSING":
                                statusMsg = "退款处理中";
                                break;
                            case "CHANGE":
                                statusMsg = "退款异常，退款到银行发现用户的卡作废或者冻结了，导致原路退款银行卡失败，可前往商户平台（pay.weixin.qq.com）-交易中心，手动处理此笔退款";
                                break;
                            default:
                                statusMsg = "未知的退款状态";
                        }
                        return Result.ok(statusMsg, status);
                    }
                } else {
                    return Result.fail(ResultCode.PAY_ORDER_QUERY_FAIL, stringMap.get("return_msg"));
                }
            default:
                return Result.fail(ResultCode.PAY_CHANNEL_NOT_SUPPORT);
        }


    }


    @Override
    public String handleAlipayNotify(Map<String, String> paramsNotify) {


        try {
            boolean signVerified = AlipaySignature.rsaCheckV1(paramsNotify, AlipayConfig.ali_public_key, AlipayConfig.input_charset);
            if (signVerified) {

                String outTradeNo = paramsNotify.get("out_trade_no");
                String totalAmount = paramsNotify.get("total_amount");
                String sellerId = paramsNotify.get("seller_id");
                String appId = paramsNotify.get("app_id");
                String tradeStatus = paramsNotify.get("trade_status");
                String gmtPayment = paramsNotify.get("gmt_payment");
                Date timePaid = null;
                try {

                    timePaid = DateUtils.parseDateStrictly(gmtPayment, "yyyy-MM-dd HH:mm:ss");
                } catch (ParseException e) {
                    e.printStackTrace();
                    return "failure";
                }

                RunfastGoodsSellRecordExample orderExample = new RunfastGoodsSellRecordExample();
                orderExample.createCriteria().andOrderCodeEqualTo(outTradeNo);

                List<RunfastGoodsSellRecord> orders = orderService.selectByExample(orderExample);
                if (!orders.isEmpty()) {
                    RunfastGoodsSellRecord order = orders.get(0);
                    if (totalAmount.equals(order.getTotalpay()) && appId.equals(AlipayConfig.aliPay_AppID)) {

                        /*WAIT_BUYER_PAY	交易创建，等待买家付款
                        TRADE_CLOSED	未付款交易超时关闭，或支付完成后全额退款
                        TRADE_SUCCESS	交易支付成功
                        TRADE_FINISHED	交易结束，不可退款*/
                        switch (tradeStatus) {
                            case "WAIT_BUYER_PAY":
                                break;
                            case "TRADE_CLOSED":
                                break;
                            case "TRADE_SUCCESS":
                            case "TRADE_FINISHED":
                                onPaidSuccess(order);
                                break;

                        }

                        return "success";
                    }
                }

            }

        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        return "failure";
    }


    @Override
    public String handleWxpayNotify(String xmlNotify) {

        Map<String, String> notifyMap = null;
        try {
            notifyMap = wxAppPay.processResponseXml(xmlNotify);
        } catch (Exception e) {
            e.printStackTrace();
            return "<xml><return_code><![CDATA[FAIL]]></return_code></xml>";
        }

        String returnCode = notifyMap.get("return_code");
        if ("SUCCESS".equals(returnCode)) {
            String resultCode = notifyMap.get("result_code");
            if ("SUCCESS".equals(resultCode)) {
                boolean signatureValid = false;
                try {
                    signatureValid = wxAppPay.isResponseSignatureValid(notifyMap);
                } catch (Exception e) {
                    e.printStackTrace();
                    return "<xml><return_code><![CDATA[FAIL]]></return_code></xml>";
                }
                if (!signatureValid) return "";
                String totalFee = notifyMap.get("total_fee");
                String tradeType = notifyMap.get("trade_type");
                String outTradeNo = notifyMap.get("out_trade_no");
                String timeEnd = notifyMap.get("time_end");
                Date timePaid = null;
                try {
                    timePaid = DateUtils.parseDateStrictly(timeEnd, "yyyyMMddHHmmss");
                } catch (ParseException e) {
                    e.printStackTrace();
                    return "<xml><return_code><![CDATA[FAIL]]></return_code></xml>";
                }


                RunfastGoodsSellRecordExample orderExample = new RunfastGoodsSellRecordExample();
                orderExample.createCriteria().andOrderCodeEqualTo(outTradeNo);
                List<RunfastGoodsSellRecord> orders = orderService.selectByExample(orderExample);
                if (!orders.isEmpty()) {
                    RunfastGoodsSellRecord order = orders.get(0);
                    if (order.getTotalpay().multiply(BigDecimal.valueOf(100)).intValue() == Integer.valueOf(totalFee)) {
                        onPaidSuccess(order);
                        return "<xml><return_code><![CDATA[SUCCESS]]></return_code></xml>";
                    }


                }
            }


        }

        return "<xml><return_code><![CDATA[FAIL]]></return_code></xml>";
    }

    private void onPaidSuccess(RunfastGoodsSellRecord order) {
        if (order.getStatus() == RunfastRefund.Status.create.getCode()) {

            RunfastGoodsSellRecord orderUpdated = new RunfastGoodsSellRecord();
            orderUpdated.setId(order.getId());
            orderUpdated.setStatus(RunfastGoodsSellRecord.Status.paid.getCode());
            orderUpdated.setStatStr("用户已付款");
            orderUpdated.setIsPay(1);
            orderUpdated.setPayTime(new Date());

            orderService.updateByPrimaryKeySelective(orderUpdated);

            /**
             * 保存订单状态
             */
            RunfastGoodsSellOutStatus goodsSellOutStatus = new RunfastGoodsSellOutStatus();

            goodsSellOutStatus.setBusinessId(order.getBusinessId());
            goodsSellOutStatus.setBusinessName(order.getBusinessName());

            goodsSellOutStatus.setCreateTime(new Date());

            goodsSellOutStatus.setGoodsSellRecordCode(order.getOrderCode());
            goodsSellOutStatus.setGoodsSellRecordId(order.getId());

            goodsSellOutStatus.setOperationId(order.getUserId());
            goodsSellOutStatus.setOperationName(order.getUserMobile());
            goodsSellOutStatus.setSort(RunfastGoodsSellRecord.Status.paid.getCode());
            goodsSellOutStatus.setStatStr("客户已付款 ");
            goodsSellOutStatus.setType(3);//操作人类型 0：后台管理员，1：商家  ，2:快递员  ，3：用户

            statusService.insertSelective(goodsSellOutStatus);

            //用户下单通知
            messagePushTask.newOrderNotify(orderService.selectByPrimaryKey(order.getId()));

            /**
             * 自动接单
             */
            RunfastBusiness business = businessService.selectByPrimaryKey(order.getBusinessId());
            Boolean autoTaking = business.getAutoTaking();
            if (autoTaking != null && autoTaking) {
                orderService.businessTake(order);
            }

        }
    }

    @Override
    public String handleWxpayRefundNotify(String xmlNotify) {


        Map<String, String> notifyMap = null;
        try {
            notifyMap = wxAppPay.processResponseXml(xmlNotify);
        } catch (Exception e) {
            e.printStackTrace();
            return "<xml><return_code><![CDATA[FAIL]]></return_code></xml>";
        }

        String returnCode = notifyMap.get("return_code");
        if ("SUCCESS".equals(returnCode)) {
            String resultCode = notifyMap.get("result_code");
            if ("SUCCESS".equals(resultCode)) {
                byte[] reqInfosDecoded = Base64.decodeBase64(notifyMap.get("req_info"));

                String appid = notifyMap.get("appid");
                String appID = wxAppPay.getConfig().getAppID();
                String key = null;
                if (appID.equals(appid)) {
                    key = wxAppPay.getConfig().getKey();
                } else {
                    key = wxPublicPay.getConfig().getKey();
                }

                String keyMd5 = DigestUtils.md5Hex(wxAppPay.getConfig().getKey()).toLowerCase();
                SecretKeySpec keySpec = new SecretKeySpec(keyMd5.getBytes(), "AES");

                Properties properties = new Properties();
                properties.setProperty(CryptoCipherFactory.CLASSES_KEY, CryptoCipherFactory.CipherProvider.JCE.getClassName());
                //Creates a CryptoCipher instance with the transformation and properties.
                final String transform = "AES/ECB/PKCS7Padding";

                String notifyDecoded = null;
                try {
                    CryptoCipher decipher = Utils.getCipherInstance(transform, properties);
                    decipher.init(DECRYPT_MODE, keySpec, null);
                    byte[] decoded = new byte[reqInfosDecoded.length * 2];
                    int outLength = decipher.doFinal(reqInfosDecoded, 0, reqInfosDecoded.length, decoded, 0);
                    notifyDecoded = new String(Arrays.copyOf(decoded, outLength));
                } catch (Exception e) {
                    e.printStackTrace();
                    return "<xml><return_code><![CDATA[FAIL]]></return_code></xml>";
                }

                Map<String, String> mapDecoded = null;
                try {
                    mapDecoded = wxAppPay.processResponseXml(notifyDecoded);
                } catch (Exception e) {
                    e.printStackTrace();
                    return "<xml><return_code><![CDATA[FAIL]]></return_code></xml>";
                }

                String refundStatus = mapDecoded.get("refund_status");
                if ("SUCCESS".equals(refundStatus)) {

                    String transactionId = mapDecoded.get("transaction_id");
                    String outTradeNo = mapDecoded.get("out_trade_no");
                    String outRefundNo = mapDecoded.get("out_refund_no");
                    String successTime = mapDecoded.get("success_time");
                    Integer refundFee = Integer.valueOf(mapDecoded.get("refund_fee"));

                    RunfastGoodsSellRecordExample orderExample = new RunfastGoodsSellRecordExample();
                    orderExample.createCriteria().andOrderCodeEqualTo(outTradeNo);
                    List<RunfastGoodsSellRecord> orders = orderService.selectByExample(orderExample);
                    if (!orders.isEmpty()) {
                        RunfastGoodsSellRecord order = orders.get(0);
                        BigDecimal amountRefunded = order.getRefund();
                        amountRefunded.add(BigDecimal.valueOf(refundFee).divide(BigDecimal.valueOf(100)));
                        if (order.getStatus() == RunfastRefund.Status.create.getCode()) {

                            RunfastGoodsSellRecord orderUpdated = new RunfastGoodsSellRecord();
                            orderUpdated.setId(order.getId());
                            orderUpdated.setIsRefund(1);
                            orderUpdated.setRefund(amountRefunded);
                            orderService.updateByPrimaryKeySelective(orderUpdated);


                            RunfastRefundExample refundExample = new RunfastRefundExample();
                            refundExample.createCriteria()
                                    .andRefund_noEqualTo(outRefundNo);
                            List<RunfastRefund> refunds = refundService.selectByExample(refundExample);
                            if (!refunds.isEmpty()) {
                                RunfastRefund refund = refunds.get(0);

                                RunfastRefund refundUpdated = new RunfastRefund();
                                refundUpdated.setId(refund.getId());
                                refundUpdated.setAmount(refundFee);
                                refundUpdated.setUpdate_time(new Date());
                                refundUpdated.setTransaction_no(transactionId);
                                refundUpdated.setStatus(RunfastRefund.Status.success.getCode());
                                refundUpdated.setSucceed(true);
                                refundUpdated.setTime_succeed(new Date());

                                refundService.updateByPrimaryKeySelective(refundUpdated);
                            }


                        }
                    }
                } else {
                    String outRefundNo = mapDecoded.get("out_refund_no");


                    RunfastRefundExample refundExample = new RunfastRefundExample();
                    refundExample.createCriteria()
                            .andRefund_noEqualTo(outRefundNo);
                    List<RunfastRefund> refunds = refundService.selectByExample(refundExample);
                    if (!refunds.isEmpty()) {
                        RunfastRefund refund = refunds.get(0);

                        RunfastRefund refundUpdated = new RunfastRefund();
                        refundUpdated.setId(refund.getId());
                        refundUpdated.setStatus(RunfastRefund.Status.fail.getCode());
                        refundUpdated.setSucceed(false);
                        refundUpdated.setFailure_code(refundStatus);


                        refundService.updateByPrimaryKeySelective(refundUpdated);

                    }
                }
                return "<xml><return_code><![CDATA[SUCCESS]]></return_code></xml>";

            }

        }
        return "<xml><return_code><![CDATA[FAIL]]></return_code></xml>";

    }



    /*public Result realPay(Channel channel, String orderNo, int amountPayable, String subject, String productCode, String timeoutExpress, String notifyUrl, String clientIp){
        Validate.notBlank(orderNo, "订单号不能为空");

        OrderExample orderExample = new OrderExample();
        orderExample.createCriteria()
                .andOrderNoEqualTo(orderNo);

        List<Order> orders = orderService.selectByExample(orderExample);
        if (orders.isEmpty()) return Result.fail(ResultCode.ORDER_NOT_EXIST);
        Order order = orders.get(0);

        switch (channel) {
            case ALIPAY_APP:
                AlipayTradeAppPayResponse response = alipayService.realPay(orderNo, amountPayable, subject, productCode, timeoutExpress, notifyUrl);
                if (!response.isSuccess())
                    return Result.fail(ResultCode.FAIL, response.getSubMsg());
                else {
                    return Result.ok("支付成功");
                }
            case WXPAY_APP:
            case WXPAY_PUBLIC:
            default:
                return Result.fail(ResultCode.PAY_CHANNEL_NOT_SUPPORT);
        }
    }*/
}

